package com.black.cat.jvm.rtda;

import com.black.cat.jvm.classfile.ByteUtil;
import lombok.Data;

import java.util.NoSuchElementException;

/**
 * @Author blackcat
 * @create 2021/8/12 15:32
 * @version: 1.0
 * @description:局部变量表
 */

public class LocalVars {

    private Slot[] localVars;


    public LocalVars(int maxLocals) {
        if (maxLocals > 0) {
            localVars = new Slot[maxLocals];
            for (int i = 0; i < maxLocals; i++) {
                localVars[i] = new Slot();
            }
        }
    }

    public void setInt(int pos, int val) {
        checkIndex(pos);
        localVars[pos].num = val;
    }

    public int getInt(int pos) throws NoSuchElementException {
        checkIndex(pos);
        return localVars[pos].num;
    }

    public void setFloat(int pos, float val) {
        checkIndex(pos);
        localVars[pos].num = Float.floatToIntBits(val);
    }

    public Float getFloat(int pos) {
        checkIndex(pos);
        return Float.intBitsToFloat(localVars[pos].num);
    }

    public void setLong(int pos, long val) {
        checkIndex(pos + 1);
        int[] ints = ByteUtil.long2IntArr(val);
        localVars[pos].num = ints[0];
        localVars[pos + 1].num = ints[1];
    }

    public long getLong(int pos) {
        checkIndex(pos + 1);
        return ByteUtil.int2Long(localVars[pos].num, localVars[pos + 1].num);
    }

    public void setDouble(int pos, double val) {
        checkIndex(pos);
        long l = Double.doubleToLongBits(val);
        setLong(pos, l);
    }

    public double getDouble(int pos) {
        long res = getLong(pos);
        return Double.longBitsToDouble(res);
    }

    public void setRef(int pos, JObject ref) {
        checkIndex(pos);
        localVars[pos].ref = ref;
    }

    public JObject getRef(int pos) {
        checkIndex(pos);
        return localVars[pos].ref;
    }

    private void checkIndex(int pos) {
        if (pos < 0 || pos >= size()) {
            throw new IllegalArgumentException("invalid index, " + pos);
        }
    }

    public int size() {
        return localVars.length;
    }



    public void setSlot(int idx, Slot slot) {
        this.localVars[idx] = slot;
    }

    public Slot[] getSlots() {
        return localVars;
    }
}
